package io.cw.service.impl.iml.background;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.cw.common.utils.StringUtils;
import io.cw.dao.background.RoomDao;
import io.cw.dto.background.RoomEditDTO;
import io.cw.entity.background.RelRoomSeatEntity;
import io.cw.entity.background.RelRoomTimeEntity;
import io.cw.entity.background.RoomEntity;
import io.cw.service.impl.background.RelRoomSeatService;
import io.cw.service.impl.background.RelRoomTimeService;
import io.cw.service.impl.background.RoomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 教室服务类
 *
 * @author cw
 */
@Service
public class RoomServiceImpl extends ServiceImpl<RoomDao, RoomEntity> implements RoomService {

    @Autowired
    private RelRoomTimeService relRoomTimeService;

    @Autowired
    private RelRoomSeatService relRoomSeatService;


    @Override
    @Transactional
    public RoomEntity add(RoomEntity roomDTO) {
        roomDTO.setId(IdWorker.getIdStr())
               .setRoomNo(this.getRoomNo())
               .setIsValid(1);

        // 保存教室信息
        this.save(roomDTO);

        // 保存教室与预约时段关系
        roomDTO.getRoomTimeList().forEach(o-> {o.setId(IdWorker.getIdStr()).setRoomId(roomDTO.getId()).setIsValid(1);});
        relRoomTimeService.batchInsert(roomDTO.getRoomTimeList());

        // 保存教室与座位关系
        List<RelRoomSeatEntity> seatEntityList = new ArrayList<>();
        for (RelRoomTimeEntity relRoomTime: roomDTO.getRoomTimeList()) {
            for (int i = 0; i < roomDTO.getSeatQty(); i++) {
                seatEntityList.add(
                        new RelRoomSeatEntity()
                                .setId(IdWorker.getIdStr())
                                .setRoomId(roomDTO.getId())
                                .setSeatNo(relRoomSeatService.getSeatNo(i, 3))
                                .setRoomTimeId(relRoomTime.getId())
                                .setStartTime(relRoomTime.getStartTime())
                                .setEndTime(relRoomTime.getEndTime())
                                .setStatus(1)
                                .setIsValid(1));
            }
        }
        relRoomSeatService.batchInsert(seatEntityList);
        return roomDTO;
    }

    private String getRoomNo() {
        LambdaQueryWrapper<RoomEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(RoomEntity::getRoomNo)
                    .last("LIMIT 1");
        RoomEntity room = this.getBaseMapper().selectOne(queryWrapper);

        String maxNo = Objects.nonNull(room) ? StringUtils.fillZeroChar(Integer.valueOf(room.getRoomNo())+1, 3) : "001";
        return maxNo;
    }


    @Override
    @Transactional
    public void edit(RoomEditDTO editDTO) {
        RoomEntity entity = this.lambdaQuery().eq(RoomEntity::getId, editDTO.getId()).one();
        if (Objects.isNull(entity)) return;
        String roomId = editDTO.getId();

        // 清楚全部关联数据
        relRoomTimeService.delateByRoomId(roomId);
        relRoomSeatService.deleteByRoomId(roomId);


        // 更新
        this.updateById(entity.setSeatQty(editDTO.getSeatQty()).setIsValid(1));

        // 新增关联数据
        // 保存教室与预约时段关系
        editDTO.getRoomTimeList().forEach(o-> {o.setId(IdWorker.getIdStr()).setRoomId(roomId);});
        relRoomTimeService.batchInsert(editDTO.getRoomTimeList());

        // 保存教室与座位关系
        List<RelRoomSeatEntity> seatEntityList = new ArrayList<>();
        for (RelRoomTimeEntity relRoomTime: editDTO.getRoomTimeList()) {
            for (int i = 0; i < editDTO.getSeatQty(); i++) {
                seatEntityList.add(
                        new RelRoomSeatEntity()
                                .setId(IdWorker.getIdStr())
                                .setRoomId(roomId)
                                .setSeatNo(relRoomSeatService.getSeatNo(i, 3))
                                .setRoomTimeId(relRoomTime.getId())
                                .setStartTime(relRoomTime.getStartTime())
                                .setEndTime(relRoomTime.getEndTime())
                                .setStatus(1)
                                .setIsValid(1));
            }
        }
        relRoomSeatService.batchInsert(seatEntityList);
    }

    @Override
    @Transactional
    public void delete(String id) {
        this.removeById(id);
        relRoomTimeService.remove(relRoomTimeService.lambdaQuery().eq(RelRoomTimeEntity::getRoomId, id));
        relRoomSeatService.remove(relRoomSeatService.lambdaQuery().eq(RelRoomSeatEntity::getRoomId, id));

    }

    @Override
    public List<RoomEntity> findAllList() {
        List<RoomEntity> resultList = new ArrayList<>();
        resultList = this.lambdaQuery().eq(RoomEntity::getIsValid, 1).orderByDesc(RoomEntity::getId).list();
        if (CollectionUtils.isEmpty(resultList)) return resultList;

        // 填充时段数据
        List<String> roomIds = resultList.stream().map(RoomEntity::getId).collect(Collectors.toList());
        List<RelRoomTimeEntity> roomTimeList = relRoomTimeService.findByRoomIds(roomIds);
        Map<String, List<RelRoomTimeEntity>> roomTimeMap = roomTimeList.stream().collect(Collectors.toMap(o -> o.getRoomId(),
                o -> new ArrayList<RelRoomTimeEntity>() {{
                    add(o);
                }}
                , (k1, k2) -> {
                    k1.addAll(k2);
                    return k1;
                }));
        resultList.forEach(room-> {room.setRoomTimeList(roomTimeMap.get(room.getId()));});
        return resultList;
    }

    @Override
    public List<RoomEntity> findListByIds(List<String> roomIds) {
        return this.lambdaQuery().eq(RoomEntity::getIsValid, 1).in(RoomEntity::getId, roomIds).list();
    }
}
